/*
 * Copyright © 2009 Gerald Isaac Schwarz
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package base;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class PieceModifier extends JDialog {
	private JLabel ownerLabel, levelLabel;
	private JSpinner levelOptions;
	private JComboBox ownerOptions;
	private JButton cancel, modifyPiece, addPlayer, modifyPlayer;
	private GridBagConstraints constraints;
	private Piece piece;
	private boolean result;
	private ArrayList<Player> players;
	private PieceModifier me = this;
	
	private ActionListener buttonListener = new ActionListener() {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getActionCommand().equals(modifyPiece.getActionCommand())) {
				setResult(true);
				setVisible(false);
			}
			else if (e.getActionCommand().equals(cancel.getActionCommand())) {
				setVisible(false);
			}
			else if (e.getActionCommand().equals(addPlayer.getActionCommand())) {
				int id = Board.nextAvailableId(players);
				
				Player newPlayer = new Player("Player " + (id + 1), id, Color.GRAY);
				Player resultPlayer = PlayerModifier.showDialog(me, "New Player", newPlayer);
				
				if (resultPlayer != null) {
					piece.setOwner(resultPlayer);
					refreshPlayers();
				}
				
			}
			else if (e.getActionCommand().equals(modifyPlayer.getActionCommand())) {
				Player cachedPlayer = (Player) ownerOptions.getSelectedItem();
				Player newPlayer = new Player(cachedPlayer.getName(), cachedPlayer.getId(), cachedPlayer.getColor());
				Player resultPlayer = PlayerModifier.showDialog(me, "Edit Player", newPlayer);
				
				if (resultPlayer != null) {
					cachedPlayer.setName(resultPlayer.getName());
					cachedPlayer.setColor(resultPlayer.getColor());
					cachedPlayer.setId(resultPlayer.getId());
					
					refreshPlayers();
				}
			}
		}
		
	};
	
	private ChangeListener levelListener = new ChangeListener() {

		@Override
		public void stateChanged(ChangeEvent e) {
			int level = (Integer) levelOptions.getValue();
			piece.setLevel(level);
		}
		
	};
	
	private ItemListener ownerListener = new ItemListener() {
		
		@Override
		public void itemStateChanged(ItemEvent e) {
//			TODO
			Player owner = (Player) ownerOptions.getSelectedItem();
			
			if (owner != null) {
				piece.setOwner(owner);
			}
		}
		
	};
	
	private void refreshPlayers() {
		Player selectedPlayer = this.piece.getOwner();
		this.ownerOptions.removeAllItems();
		
		ArrayList<Player> players = new ArrayList<Player>(this.players);
		
		if (!players.contains(selectedPlayer)) {
			players.add(selectedPlayer);
		}
		
		for (Player player : players) {
			this.ownerOptions.addItem(player);
		}
		
//		TODO
		this.ownerOptions.setSelectedItem(selectedPlayer);
	}
	
	@Override
	public void setVisible(boolean visible) {
		if (visible) {
			this.setResult(false);
		}
		
		super.setVisible(visible);
	}
	
	public static Piece showDialog(Window window, String title, Piece piece, ArrayList<Player> players) {
		PieceModifier pieceModifier = new PieceModifier(window, title, piece, players);
		
		pieceModifier.setVisible(true);
		
		if (pieceModifier.isResult()) {
			return pieceModifier.getPiece();
		}
		else {
			return null;
		}
	}
	
	public PieceModifier(Window window, String title, Piece piece, ArrayList<Player> players) {
		super(window, title, JDialog.DEFAULT_MODALITY_TYPE);
		this.players = players;
		
		this.getContentPane().setLayout(new GridBagLayout());
		
		this.ownerLabel = new JLabel("Owner");
		this.ownerOptions = new JComboBox();
		this.ownerOptions.addItemListener(this.ownerListener);
		this.ownerLabel.setLabelFor(this.ownerOptions);
		
		this.setPiece(piece);
		
		this.levelLabel = new JLabel("Level");
		this.levelOptions = new JSpinner(new SpinnerNumberModel(1, 1, 50, 1));
		this.levelOptions.addChangeListener(this.levelListener);
		this.levelLabel.setLabelFor(this.levelOptions);
		
		this.addPlayer = new JButton("New");
		this.addPlayer.setActionCommand("New Player");
		this.addPlayer.addActionListener(this.buttonListener);
		
		this.modifyPlayer = new JButton("Edit");
		this.modifyPlayer.setActionCommand("Edit Player");
		this.modifyPlayer.addActionListener(this.buttonListener);
		
		this.cancel = new JButton("Cancel");
		this.cancel.setActionCommand("Cancel");
		
		this.modifyPiece = new JButton("Apply");
		this.modifyPiece.setActionCommand("Apply");
		
		this.cancel.addActionListener(this.buttonListener);
		this.modifyPiece.addActionListener(this.buttonListener);
		
		this.constraints = new GridBagConstraints();
		this.constraints.gridx = 0;
		this.constraints.gridy = 0;
		this.constraints.gridwidth = 1;
		this.constraints.anchor = GridBagConstraints.LINE_END;
		this.constraints.insets = new Insets(5, 5, 5, 5);
		this.constraints.fill = GridBagConstraints.NONE;
		this.getContentPane().add(this.ownerLabel, this.constraints);
		
		this.constraints.gridx = 1;
		this.constraints.gridy = 0;
		this.constraints.gridwidth = 2;
		this.constraints.fill = GridBagConstraints.HORIZONTAL;
		this.getContentPane().add(this.ownerOptions, this.constraints);
		
		this.constraints.gridx = 3;
		this.constraints.gridy = 0;
		this.constraints.gridwidth = 1;
		this.constraints.fill = GridBagConstraints.HORIZONTAL;
		this.getContentPane().add(this.modifyPlayer, this.constraints);
		
		this.constraints.gridx = 4;
		this.constraints.gridy = 0;
		this.constraints.gridwidth = 1;
		this.constraints.fill = GridBagConstraints.HORIZONTAL;
		this.getContentPane().add(this.addPlayer, this.constraints);
		
		this.constraints.gridx = 0;
		this.constraints.gridy = 1;
		this.constraints.gridwidth = 1;
		this.constraints.fill = GridBagConstraints.NONE;
		this.getContentPane().add(this.levelLabel, this.constraints);
		
		this.constraints.gridx = 1;
		this.constraints.gridy = 1;
		this.constraints.gridwidth = 4;
		this.constraints.fill = GridBagConstraints.HORIZONTAL;
		this.getContentPane().add(this.levelOptions, this.constraints);
		
		this.constraints.gridx = 3;
		this.constraints.gridy = 2;
		this.constraints.gridwidth = 1;
		this.constraints.fill = GridBagConstraints.BOTH;
		this.getContentPane().add(this.cancel, this.constraints);
		
		this.constraints.gridx = 4;
		this.constraints.gridy = 2;
		this.constraints.gridwidth = 1;
		this.constraints.fill = GridBagConstraints.NONE;
		this.getContentPane().add(this.modifyPiece, this.constraints);
		
		this.cancel.setMnemonic(KeyEvent.VK_C);
		this.modifyPiece.setMnemonic(KeyEvent.VK_A);
		this.addPlayer.setMnemonic(KeyEvent.VK_N);
		this.modifyPlayer.setMnemonic(KeyEvent.VK_E);
		
		this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
		this.pack();
		this.setResizable(false);
	}
	
	private void setResult(boolean result) {
		this.result = result;
	}
	
	public boolean isResult() {
		return this.result;
	}
	
	private void setPiece(Piece piece) {
		this.piece = piece;
		this.refreshPlayers();
	}
	
	public Piece getPiece() {
		return this.piece;
	}
}
